//----------------------------------------------------------------------------------------
// @Project Includes
#include "includes.h"

//----------------------------------------------------------------------------------------
// @Local Macro Define in the module

//----------------------------------------------------------------------------------------
// @Local Type defines in the module

//----------------------------------------------------------------------------------------
// @Global Variables define in the module
stc_srvcan_t g_stcSrvCan = {0};

//----------------------------------------------------------------------------------------
// @Prototypes of functions in the module
static void srv_can_unpack(uint32_t canid,uint8_t * pMsg);
static void srv_can_receive(void);
static void srv_can_send(void);
static uint8_t srv_can_is_chaodian_protocol(uint32_t can_id);

//========================================================================================
/*
 * @Functions:   static uint8_t srv_can_is_chaodian_protocol(uint32_t can_id)
 * @Description: 判断是否为超电协议
 * @Parameters:  can_id - CAN ID
 * @Return:      0-不是, 1-是
 */
static uint8_t srv_can_is_chaodian_protocol(uint32_t can_id)
{
    uint8_t func_code, dst_addr, src_addr;
    uint16_t reg_addr;
    
    // 解析CAN ID
    if (cd_can_parse_id(can_id, &func_code, &reg_addr, &dst_addr, &src_addr))
    {
        // 检查功能码是否为超电协议
        if (func_code == CD_FUNC_READ_REG || func_code == CD_FUNC_WRITE_REG ||
            func_code == CD_FUNC_READ_REG_ERROR || func_code == CD_FUNC_WRITE_REG_ERROR ||
            func_code == CD_FUNC_EVENT_REPORT || func_code == CD_FUNC_UPGRADE)
        {
            return 1;
        }
    }
    
    return 0;
}

//========================================================================================
 /*
 * @Functions:   static void srv_can_unpack(uint32_t canid,uint8_t * pMsg)
 * @Description: 解析CAN协议
 * @Parameters:  NONE
 * @Return:      NONE
 */
static void srv_can_unpack(uint32_t canid,uint8_t * pMsg)
{
    // 首先检查是否为超电协议
    if (cd_can_is_for_me(canid, CD_DEVICE_ADDR_BMS))
    {
        // 处理超电协议
        cd_can_process_message(canid, pMsg, 8);
        return;
    }
    
    // 处理原有的卡奥斯协议
    switch(canid)
    {
        case CAN_UPG_INDEX_ID:
            memcpy(&g_stcSrvCan.unfirmwareInfo.Data[0] ,pMsg,8);
						srv_j1939_fwInfoCallback();
            break;
        case CAN_UPG_DATA_ID:
            memcpy(&g_stcSrvCan.unfirmwareData.Data[0] ,pMsg,8);
						srv_j1939_fwDataCallback();
            break;	
        case CAN_UPG_RESULT_ID:
            memcpy(&g_stcSrvCan.unfirmwareResult.Data[0] ,pMsg,8);
						if (srv_j1939_fwResultCallback() == true)
						{
								srv_can_send();
								printf("Modbus:<< The upgrade is complete, restart and enter BOOT....\r\n ");
								drv_systick_delay_ms(50);	
								NVIC_SystemReset();	
						}
						else
						{
							
						}
            break;
						
        case CAN_READ_ID:
						srv_j1939_readCallback(pMsg,8);
						g_stcVar.u16sleepWaitTime = g_stcParm.stcConfig.u16curTime;//g_stcParm.stcConfig.u16curTime;	
            break;
        case CAN_WRITE_ID:
						srv_j1939_writeCallback(pMsg,8);
            break;	

        default:
            break;	
    }
}

 /*
 * @Functions:   static void srv_can_receive(void)
 * @Description: CAN receives data.
 * @Parameters:  NONE
 * @Return:      NONE
 */
static void srv_can_receive(void)
{
    if (g_stccan.vu8canRxMQPushLen != g_stccan.vu8canRxMQPopLen)
    {
        if (g_stccan.vu8canRxMQPopLen < CAN_MAX_RX_SIZE)/*保护，防止溢出*/
        {
            CAN_DEBUG("CAN:<< rc %02x  %02x %08x   %02x  %02x %02x %02x %02x %02x %02x %02x %02x\r\n",
										 (unsigned int)g_stccan.canRxMessage[g_stccan.vu8canRxMQPopLen].RTR,
										 (unsigned int)g_stccan.canRxMessage[g_stccan.vu8canRxMQPopLen].IDE,
                     (unsigned int)g_stccan.canRxMessage[g_stccan.vu8canRxMQPopLen].ExtId,
                     (uint8_t)g_stccan.canRxMessage[g_stccan.vu8canRxMQPopLen].DLC,
                     g_stccan.canRxMessage[g_stccan.vu8canRxMQPopLen].Data[0],
                     g_stccan.canRxMessage[g_stccan.vu8canRxMQPopLen].Data[1],
                     g_stccan.canRxMessage[g_stccan.vu8canRxMQPopLen].Data[2],
                     g_stccan.canRxMessage[g_stccan.vu8canRxMQPopLen].Data[3],
                     g_stccan.canRxMessage[g_stccan.vu8canRxMQPopLen].Data[4],
                     g_stccan.canRxMessage[g_stccan.vu8canRxMQPopLen].Data[5],
                     g_stccan.canRxMessage[g_stccan.vu8canRxMQPopLen].Data[6],
                     g_stccan.canRxMessage[g_stccan.vu8canRxMQPopLen].Data[7]);
						srv_can_unpack((unsigned int)g_stccan.canRxMessage[g_stccan.vu8canRxMQPopLen].ExtId,&g_stccan.canRxMessage[g_stccan.vu8canRxMQPopLen].Data[0]);				 
						memset(&g_stccan.canRxMessage[g_stccan.vu8canRxMQPopLen].Data[0] ,0x00,8);
        }
        if(g_stccan.vu8canRxMQPopLen++ >= CAN_MAX_RX_SIZE)
        {
            g_stccan.vu8canRxMQPopLen = 0;
        }
    }
    else
    {
        //g_stccan.vu8canRxMQPushLen = 0;
        //g_stccan.vu8canRxMQPopLen = 0;
    }
}

/*
 * @Functions:   static void srv_can_send(void)
 * @Description: CAN发送任务
 * @Parameters:  NONE
 * @Return:      NONE
 */
static void srv_can_send(void)
{
    uint8_t TransmitMailbox = 0;
    uint16_t Time_out       = 1200;//0xFFFF(30ms太长);

    /*实时发送数据*/
    if (g_stccan.vu8canTxMQPushLen > g_stccan.vu8canTxMQPopLen)
    {
        if (g_stccan.vu8canTxMQPopLen < CAN_MAX_TX_SIZE)/*保护，防止溢出*/
        {
            TransmitMailbox = drv_can_txMessage(CAN,&g_stccan.canTxMessage[g_stccan.vu8canTxMQPopLen]);;

            CAN_DEBUG("CAN:<< tx %02x  %02x %08x   %02x  %02x %02x %02x %02x %02x %02x %02x %02x  %d  %d\r\n",
										 (unsigned int)g_stccan.canTxMessage[g_stccan.vu8canTxMQPopLen].RTR,
										 (unsigned int)g_stccan.canTxMessage[g_stccan.vu8canTxMQPopLen].IDE,
                     (unsigned int)g_stccan.canTxMessage[g_stccan.vu8canTxMQPopLen].ExtId,
                     (uint8_t)g_stccan.canTxMessage[g_stccan.vu8canTxMQPopLen].DLC,
                     g_stccan.canTxMessage[g_stccan.vu8canTxMQPopLen].Data[0],
                     g_stccan.canTxMessage[g_stccan.vu8canTxMQPopLen].Data[1],
                     g_stccan.canTxMessage[g_stccan.vu8canTxMQPopLen].Data[2],
                     g_stccan.canTxMessage[g_stccan.vu8canTxMQPopLen].Data[3],
                     g_stccan.canTxMessage[g_stccan.vu8canTxMQPopLen].Data[4],
                     g_stccan.canTxMessage[g_stccan.vu8canTxMQPopLen].Data[5],
                     g_stccan.canTxMessage[g_stccan.vu8canTxMQPopLen].Data[6],
                     g_stccan.canTxMessage[g_stccan.vu8canTxMQPopLen].Data[7],
                     g_stccan.vu8canTxMQPushLen,g_stccan.vu8canTxMQPopLen); 
						while ((CAN_TransmitSTS(CAN, TransmitMailbox) != CANTXSTSOK) && (Time_out != 0)) Time_out--;  										 
        }
        if(g_stccan.vu8canTxMQPopLen++ >= CAN_MAX_TX_SIZE)
        {
            g_stccan.vu8canTxMQPopLen = 0;
        }
    }
    else
    {
        if ((g_stccan.vu8canTxMQPushLen != 0)&&(g_stccan.vu8canTxMQPopLen != 0))
        {
            g_stccan.vu8canTxMQPushLen = 0;
            g_stccan.vu8canTxMQPopLen = 0;
        }
    }
    
}


/*
 * @Functions:   void srv_can_task(void)
 * @Description: can任务函数
 * @Parameters:  NONE
 * @Return:      NONE
 */
void srv_can_task(void)
{
    srv_can_receive();
    srv_can_send();
}



// =======================================================================================
// End of file.
// =======================================================================================
